package com.kurt.service.impl;

import com.kurt.dto.OrganizationDTO;
import com.kurt.dto.create.OrganizationCreateRequest;
import com.kurt.dto.query.OrganizationQueryRequest;
import com.kurt.dto.update.OrganizationUpdateRequest;
import com.kurt.entity.SysOrganization;
import com.kurt.entity.SysOrganizationExtension;
import com.kurt.entity.SysUser;
import com.kurt.repository.SysOrganizationExtensionRepository;
import com.kurt.repository.SysOrganizationRepository;
import com.kurt.repository.SysUserRepository;
import com.kurt.service.OrganizationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 组织服务实现类
 * 实现组织相关的业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrganizationServiceImpl extends BaseServiceImpl<SysOrganization, Long> implements OrganizationService {

    private final SysOrganizationRepository organizationRepository;
    private final SysOrganizationExtensionRepository organizationExtensionRepository;
    private final SysUserRepository userRepository;

    @Override
    protected SysOrganizationRepository getRepository() {
        return organizationRepository;
    }

    @Override
    protected SysOrganizationRepository getSpecificationExecutor() {
        return organizationRepository;
    }

    @Override
    @Transactional
    public OrganizationDTO createOrganization(OrganizationCreateRequest createRequest) {
        log.info("创建组织: {}", createRequest.getName());

        // 检查组织名称是否已存在
        if (organizationRepository.findByName(createRequest.getName()).isPresent()) {
            throw new RuntimeException("组织名称已存在");
        }

        // 创建组织实体
        SysOrganization organization = new SysOrganization();
        BeanUtils.copyProperties(createRequest, organization);
        organization.setCreateTime(LocalDateTime.now());
        organization.setUpdateTime(LocalDateTime.now());

        // 计算组织层级
        if (createRequest.getParentId() != null && createRequest.getParentId() > 0) {
            Optional<SysOrganization> parentOpt = organizationRepository.findById(createRequest.getParentId());
            if (parentOpt.isPresent()) {
                organization.setLevel(parentOpt.get().getLevel() + 1);
            }
        } else {
            organization.setLevel(1);
        }

        // 保存组织
        organization = organizationRepository.save(organization);

        // 创建组织扩展信息
        if (createRequest.getOrganizationExtension() != null) {
            SysOrganizationExtension extension = new SysOrganizationExtension();
            extension.setId(organization.getId());
            BeanUtils.copyProperties(createRequest.getOrganizationExtension(), extension);
            extension.setCreateTime(LocalDateTime.now());
            extension.setUpdateTime(LocalDateTime.now());
            organizationExtensionRepository.save(extension);
        }

        log.info("组织创建成功: {}", organization.getName());
        return convertToOrganizationDTO(organization);
    }

    @Override
    @Transactional
    public OrganizationDTO updateOrganization(OrganizationUpdateRequest updateRequest) {
        log.info("更新组织: {}", updateRequest.getId());

        // 查找组织
        SysOrganization organization = getById(updateRequest.getId());

        // 检查组织名称是否已存在（排除自己）
        if (StringUtils.hasText(updateRequest.getName()) &&
                !updateRequest.getName().equals(organization.getName()) &&
                organizationRepository.findByName(updateRequest.getName()).isPresent()) {
            throw new RuntimeException("组织名称已存在");
        }

        // 更新组织信息
        if (StringUtils.hasText(updateRequest.getName())) {
            organization.setName(updateRequest.getName());
        }
        if (updateRequest.getParentId() != null) {
            organization.setParentId(updateRequest.getParentId());
        }
        if (updateRequest.getSortOrder() != null) {
            organization.setSortOrder(updateRequest.getSortOrder());
        }
        if (updateRequest.getStatus() != null) {
            organization.setStatus(updateRequest.getStatus());
        }
        if (StringUtils.hasText(updateRequest.getRemark())) {
            organization.setRemark(updateRequest.getRemark());
        }
        organization.setUpdateTime(LocalDateTime.now());

        // 保存组织
        organization = organizationRepository.save(organization);

        // 更新组织扩展信息
        if (updateRequest.getOrganizationExtension() != null) {
            Optional<SysOrganizationExtension> extensionOpt = organizationExtensionRepository.findById(organization.getId());
            if (extensionOpt.isPresent()) {
                SysOrganizationExtension extension = extensionOpt.get();
                BeanUtils.copyProperties(updateRequest.getOrganizationExtension(), extension);
                extension.setUpdateTime(LocalDateTime.now());
                organizationExtensionRepository.save(extension);
            } else {
                // 创建新的扩展信息
                SysOrganizationExtension extension = new SysOrganizationExtension();
                extension.setId(organization.getId());
                BeanUtils.copyProperties(updateRequest.getOrganizationExtension(), extension);
                extension.setCreateTime(LocalDateTime.now());
                extension.setUpdateTime(LocalDateTime.now());
                organizationExtensionRepository.save(extension);
            }
        }

        log.info("组织更新成功: {}", organization.getName());
        return convertToOrganizationDTO(organization);
    }

    @Override
    public OrganizationDTO getOrganizationById(Long id) {
        SysOrganization organization = getById(id);
        return convertToOrganizationDTO(organization);
    }

    @Override
    public Page<OrganizationDTO> getOrganizationPage(OrganizationQueryRequest queryRequest) {
        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(queryRequest.getOrderDirection()), queryRequest.getOrderBy());
        Pageable pageable = PageRequest.of(queryRequest.getPageNum() - 1, queryRequest.getPageSize(), sort);

        // 构建查询条件
        Specification<SysOrganization> spec = buildOrganizationSpecification(queryRequest);

        // 执行分页查询
        Page<SysOrganization> organizationPage = organizationRepository.findAll(spec, pageable);

        // 转换为DTO
        return organizationPage.map(this::convertToOrganizationDTO);
    }

    @Override
    public List<OrganizationDTO> getOrganizationList(OrganizationQueryRequest queryRequest) {
        // 构建查询条件
        Specification<SysOrganization> spec = buildOrganizationSpecification(queryRequest);

        // 执行查询
        List<SysOrganization> organizations = organizationRepository.findAll(spec);

        // 转换为DTO
        return organizations.stream().map(this::convertToOrganizationDTO).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public boolean deleteOrganization(Long id) {
        log.info("删除组织: {}", id);

        // 检查是否有子组织
        List<SysOrganization> children = organizationRepository.findByParentId(id);
        if (!children.isEmpty()) {
            throw new RuntimeException("该组织下还有子组织，无法删除");
        }

        // 删除组织扩展信息
        organizationExtensionRepository.deleteById(id);

        // 删除组织
        organizationRepository.deleteById(id);

        log.info("组织删除成功: {}", id);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteOrganizations(List<Long> ids) {
        log.info("批量删除组织: {}", ids);

        for (Long id : ids) {
            deleteOrganization(id);
        }

        log.info("批量删除组织成功: {}", ids);
        return true;
    }

    @Override
    public List<OrganizationDTO> getOrganizationTree(Long parentId) {
        // 获取指定父ID下的直接子组织
        List<SysOrganization> organizations = organizationRepository.findByParentIdAndStatusOrderBySortOrderAsc(parentId, 1);

        // 转换为DTO并递归构建子组织
        return organizations.stream()
                .map(organization -> {
                    OrganizationDTO organizationDTO = convertToOrganizationDTO(organization);
                    // 递归获取子组织
                    List<OrganizationDTO> children = getOrganizationTree(organization.getId());
                    organizationDTO.setChildren(children);
                    return organizationDTO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<OrganizationDTO> getAllOrganizationTree() {
        return getOrganizationTree(0L);
    }

    @Override
    public List<OrganizationDTO> getChildrenByParentId(Long parentId) {
        List<SysOrganization> organizations = organizationRepository.findByParentId(parentId);
        return organizations.stream().map(this::convertToOrganizationDTO).collect(Collectors.toList());
    }

    @Override
    public boolean existsByName(String name) {
        return organizationRepository.findByName(name).isPresent();
    }

    @Override
    public boolean existsByNameAndIdNot(String name, Long excludeId) {
        Optional<SysOrganization> orgOpt = organizationRepository.findByName(name);
        return orgOpt.isPresent() && !orgOpt.get().getId().equals(excludeId);
    }

    @Override
    @Transactional
    public boolean moveOrganization(Long id, Long newParentId) {
        log.info("移动组织: id={}, newParentId={}", id, newParentId);

        SysOrganization organization = getById(id);

        // 检查不能移动到自己的子组织下
        if (isDescendant(id, newParentId)) {
            throw new RuntimeException("不能移动到自己的子组织下");
        }

        organization.setParentId(newParentId);
        organization.setUpdateTime(LocalDateTime.now());

        // 重新计算层级
        if (newParentId != null && newParentId > 0) {
            Optional<SysOrganization> parentOpt = organizationRepository.findById(newParentId);
            if (parentOpt.isPresent()) {
                organization.setLevel(parentOpt.get().getLevel() + 1);
            }
        } else {
            organization.setLevel(1);
        }

        organizationRepository.save(organization);

        log.info("组织移动成功: id={}, newParentId={}", id, newParentId);
        return true;
    }

    @Override
    @Transactional
    public boolean updateSortOrder(Long id, Integer sortOrder) {
        log.info("更新组织排序: id={}, sortOrder={}", id, sortOrder);

        SysOrganization organization = getById(id);
        organization.setSortOrder(sortOrder);
        organization.setUpdateTime(LocalDateTime.now());
        organizationRepository.save(organization);

        log.info("组织排序更新成功: id={}, sortOrder={}", id, sortOrder);
        return true;
    }

    /**
     * 检查是否为后代组织
     *
     * @param ancestorId   祖先组织ID
     * @param descendantId 后代组织ID
     * @return 是否为后代
     */
    private boolean isDescendant(Long ancestorId, Long descendantId) {
        if (descendantId == null || descendantId <= 0) {
            return false;
        }

        List<SysOrganization> children = organizationRepository.findByParentId(ancestorId);
        for (SysOrganization child : children) {
            if (child.getId().equals(descendantId)) {
                return true;
            }
            if (isDescendant(child.getId(), descendantId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 构建组织查询条件
     *
     * @param queryRequest 查询请求
     * @return 查询条件
     */
    private Specification<SysOrganization> buildOrganizationSpecification(OrganizationQueryRequest queryRequest) {
        return (root, query, cb) -> {
            List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();

            // 组织名称模糊查询
            if (StringUtils.hasText(queryRequest.getName())) {
                predicates.add(cb.like(root.get("name"), "%" + queryRequest.getName() + "%"));
            }

            // 父组织ID查询
            if (queryRequest.getParentId() != null) {
                predicates.add(cb.equal(root.get("parentId"), queryRequest.getParentId()));
            }

            // 组织层级查询
            if (queryRequest.getLevel() != null) {
                predicates.add(cb.equal(root.get("level"), queryRequest.getLevel()));
            }

            // 状态查询
            if (queryRequest.getStatus() != null) {
                predicates.add(cb.equal(root.get("status"), queryRequest.getStatus()));
            }

            // 创建时间范围查询
            if (StringUtils.hasText(queryRequest.getCreateTimeStart())) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeStart())));
            }
            if (StringUtils.hasText(queryRequest.getCreateTimeEnd())) {
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeEnd())));
            }

            return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
        };
    }

    /**
     * 转换组织实体为DTO
     *
     * @param organization 组织实体
     * @return 组织DTO
     */
    private OrganizationDTO convertToOrganizationDTO(SysOrganization organization) {
        OrganizationDTO organizationDTO = new OrganizationDTO();
        BeanUtils.copyProperties(organization, organizationDTO);

        // 获取父组织名称
        if (organization.getParentId() != null && organization.getParentId() > 0) {
            Optional<SysOrganization> parentOpt = organizationRepository.findById(organization.getParentId());
            if (parentOpt.isPresent()) {
                organizationDTO.setParentName(parentOpt.get().getName());
            }
        }

        // 获取组织扩展信息
        Optional<SysOrganizationExtension> extensionOpt = organizationExtensionRepository.findById(organization.getId());
        if (extensionOpt.isPresent()) {
            OrganizationDTO.OrganizationExtensionDTO extensionDTO = new OrganizationDTO.OrganizationExtensionDTO();
            BeanUtils.copyProperties(extensionOpt.get(), extensionDTO);

            // 获取负责人姓名
            if (extensionOpt.get().getManagerId() != null) {
                Optional<SysUser> userOpt = userRepository.findById(extensionOpt.get().getManagerId());
                if (userOpt.isPresent()) {
                    extensionDTO.setManagerName(userOpt.get().getRealName());
                }
            }

            organizationDTO.setOrganizationExtension(extensionDTO);
        }

        return organizationDTO;
    }
}
